/**
 * @export
 * @class Skybox
 * @classdesc 天空盒子
 * @property {Object} 地图容器 - SchoolLab实例
 * @property {String} name - 名称
 * @property {String} color - 颜色
 * @property {Number} opacity - 透明度
 * @property {Number} radius - 半径
 * @property {Number} renderOrder - 层叠顺序
 * @property {Number} startPolarAngle - 起始角度
 * @property {Number} polarAngle - 结束角度
 * @property {String} map - 贴图
 * @example
 * var skybox = new Skybox(viewer, {
 *   radius: 4,
 *   color: '#ff0000',
 *   opacity: 0.5,
 *   renderOrder: 20,
 *   name: 'skybox',
 *   map: './image/skybox.png'
 * })
 */
import { extend } from './util'
import { EARTH_RADIUS } from './Constant'
import Feature from './Feature'
export default class Skybox {
  constructor(viewer, options) {
    const opts = extend({
      name: "skybox",
      color: "#ffffff",
      opacity: 1,
      radius: EARTH_RADIUS,
      startPolarAngle: 0,
      polarAngle: Math.PI / 2,
      map: '',
    }, options)


    /** @member {SchoolLab} - 地图容器 */
    this.viewer = viewer
    
    /** @member {String} - 名称 */
    this.name = opts.name
    
    /** @member {Color} - 颜色 */
    this.color = opts.color
    
    /** @member {Number} - 透明度 */
    this.opacity = opts.opacity
    
    /** @member {Number} - 半径 */
    this.radius = opts.radius
    
    /** @member {Number} - 起始角度 */
    this.startPolarAngle = opts.startPolarAngle
    
    /** @member {Number} - 结束角度 */
    this.polarAngle = opts.polarAngle
    
    /** @member {String} - 天空贴图 */
    this.map = opts.map
    
    /** @member {THREE.Mesh} - mesh对象 */
    this.entity = null

    Feature.apply(this)

    this._init()
  }

  // 初始化组件
  _init() {
    let geometry = this._initGeometry()
    let material = this._initMaterial()

    const mesh = new THREE.Mesh(geometry, material)
    mesh.name = this.name
    mesh.rotation.x = Math.PI / 2

    this.entity = mesh
    this.viewer.world.add(mesh)
  }

  // 初始化几何体
  _initGeometry() {
    const geometry = new THREE.SphereBufferGeometry(this.radius, 64, 64, 0, Math.PI * 2, this.startPolarAngle, this.polarAngle)
    return geometry
  }

  // 初始化材质
  _initMaterial() {
    const loader = new THREE.TextureLoader()
    const map = loader.load(this.map)

    const uniforms = {
      map: { type: "t", value: map },
      color: { type: "c", value: new THREE.Color(this.color) },
      opacity: { type: "f", value: this.opacity }
    }

    let vs = this._initVS()
    let fs = this._initFS()
    const material = new THREE.ShaderMaterial({
      uniforms: uniforms,
      vertexShader: vs,
      fragmentShader: fs,
      transparent: true,
      depthWrite: false,
      depthTest: true,
      side: THREE.BackSide
    })

    return material
  }

  // 初始化vertexShader
  _initVS() {
    const vs = `
      precision lowp float;
      precision lowp int;
      
      varying vec2 vUv;
      void main() {
        vUv = uv;
        gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
      }
    `
    return vs
  }

  // 初始化fragmentShader
  _initFS() {
    const fs = `
      precision lowp float;
      precision lowp int;

      varying vec2 vUv;
      uniform sampler2D map;
      uniform vec3 color;
      void main() {
        gl_FragColor = texture2D(map, vUv);
        gl_FragColor.rgb *= color;
      }
    `
    return fs
  }

  // 组件销毁
  destroy() {
    this._disposeHierarchy(this.entity, this._dispose)
    this.viewer.world.remove(this.entity)
    this.entity = null
  }
}
